package com.autonavi.yunda.yunji.common.utils.geo;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;
import org.springframework.stereotype.Component;

/**;
 * @author: liuchunyang;
 * @create: 2022-06-16 21:24;
 * @program: idc-di-uolap;
 * @description) wkt切块函数，返回值包含块与wkt的交集比例
 **/
;

@Component
public class Wkt2BlockFun2 {
    public static final double mj_cubelist = 100d*100d;
    private WKTArea wktArea = new WKTArea();

    public static void main(String[] args) throws Exception {
        Wkt2BlockFun2 t = new Wkt2BlockFun2();
        String id = "A1";
//        String wkt = "116.424683 39.909334,116.41404 39.8988,116.425369 39.894322,116.441506 39.90196,116.424683 39.909334";
        String wkt = "116.777875 40.226926,116.789125 40.226098,116.799962 40.223646,116.809987 40.219659,116.819566 40.213733,116.826755 40.20707,116.832147 40.199482,116.835546 40.191246,116.836834 40.181881,116.835751 40.173286,116.832541 40.165007,116.827323 40.157348,116.819566 40.150029,116.810845 40.144537,116.800912 40.140417,116.790133 40.13782,116.777875 40.136836,116.766625 40.137664,116.755788 40.140116,116.745763 40.144103,116.736184 40.150029,116.728995 40.156692,116.723603 40.16428,116.720204 40.172516,116.718916 40.181881,116.719999 40.190476,116.723209 40.198755,116.728427 40.206414,116.736184 40.213733,116.744905 40.219225,116.754838 40.223345,116.765617 40.225942,116.777875 40.226926";
        int scale = 100;
        List<String> pointArray = Arrays.asList(wkt.split(","));
        for (int i=0;i<100;i++) {
            long start = System.currentTimeMillis();
             t.process(scale,pointArray);
//            for (Map.Entry<String, BlockInfo> entry : process.entrySet()) {
//                BlockInfo value = entry.getValue();
//                System.out.println(value.toString());
//            }
            System.out.println("总耗时----->" + i + "--->" + (System.currentTimeMillis() - start));
        }
    }

    public List<GeoBlock> process(int scale,List<String> pointArray) throws Exception {
        //用于判断块与wkt相交关系的变量
        return GeoBlockMgr.CalcFixedBlocks2(GeoLatLon.wktTansGeoLatLon2(pointArray), scale);
    }

    private static String zfill(Object obj, int length) {
        String str = String.valueOf(obj);
        int strLen = str.length();
        if (strLen >= length) {
            return str.substring(strLen - length, strLen);
        } else {
            StringBuilder zero = new StringBuilder();
            for (int i = 0; i < length - strLen; i++) {
                zero.append("0");
            }
            return zero + str;
        }
    }


    public static void forward(String geoId, float proportion, Map<String, BlockInfo> result) {
        BlockInfo blockInfo = new BlockInfo();
        blockInfo.setGeoId(geoId);
        blockInfo.setProportion(proportion);
        result.put(geoId, blockInfo);
    }

    // 获取外包函数 格式 xmin ymin,xmax ymax;
    private static String GetEnvelope(List<String> pointArray) {
        /*'' ';
            :param pointList:list[(lon, lat)...]多边形点的顺序需根据顺时针或逆时针，不能乱;
        '' ';*/
        float xmin = 180;
        float ymin = 90;
        float xmax = 0;
        float ymax = 0;
        int iCount = len(pointArray);
        String[] s;
        for (int i = 0; i < iCount; i++) {
            s = pointArray.get(i).split(" ");
            float px = Float.parseFloat(s[0]);
            float py = Float.parseFloat(s[1]);

            if (px < xmin) {
                xmin = px;
            }
            if (px > xmax){
                xmax = px;
            }
            if (py < ymin){
                ymin = py;
            }
            if (py > ymax){
                ymax = py;
            }
        }
        return str(xmin) + ' ' + str(ymin) + ',' + str(xmax) + ' ' + str(ymax);
    }


    // 判断 点x y 在向量 x1 y1 x2 y2 的左侧还是右侧，大于0位左侧 小于0位右侧;
    private static float IsInside(float x1, float y1, float x2, float y2, float x, float y) {

        return (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1);
    }

    ;

    //获取两条线的交点位置;
    private static String GetJiaoDian(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
        float x, k2, b2, y, k1, b1;
        if (x1 == x2) {
            x = x1;
            k2 = (y4 - y3) / (x4 - x3);
            b2 = y3 - k2 * x3;
            y = k2 * x + b2;
            return str(x) + ' ' + str(y);
        }

        if (x3 == x4) {
            x = x3;
            k1 = (y2 - y1) / (x2 - x1);
            b1 = y1 - k1 * x1;
            y = k1 * x + b1;
            return str(x) + ' ' + str(y);
        }
        k1 = (y2 - y1) / (x2 - x1);
        k2 = (y4 - y3) / (x4 - x3);
        b1 = y1 - k1 * x1;
        b2 = y3 - k2 * x3;
        if (k1 == k2) {
            x = 0;
            y = 0;
        } else {
            x = (b2 - b1) / (k1 - k2);
            y = k1 * x + b1;
        }
        return str(x) + ' ' + str(y);
    }


    //多边形的裁切;
    public static List<String> CutDuobianxing(List<String> cubeArray, List<String> pointArray) {
        // cubeList='1 1,1 5,5 5,5 1';
        // pointList='2 0,2 2,6 2,6 0,2 0';;
//        List<String> cubeArray = Arrays.asList(cubeList.split(","));
//        List<String> pointArray = Arrays.asList(pointList.split(","));

        List<String> temparray = null;
//        int k = -1;

        int cubeCount = cubeArray.size();
        int pointCount = pointArray.size();
        // 0 在外侧 1在内测;
        int flag = 0;
        if (cubeCount < 3) {
            return Lists.newArrayList();
        }
        //删除wkt最后一个重复的节点;
//        if (pointArray.get(0) == pointArray.get(pointCount - 1)) {
//            pointArray.subList(0, pointCount - 2);
//            pointCount = len(pointArray);
//        }

        String[] s;
        for (int i = 0; i < cubeCount; i++) {
            // 裁剪框的;
            //print(i);
            s = cubeArray.get(i).split(" ");
            float xstart = Float.parseFloat(s[0]);
            float ystart = Float.parseFloat(s[1]);

            float xend = 0;
            float yend = 0;
            if (i == cubeCount - 1) {
                xend = Float.parseFloat(cubeArray.get(0).split(" ")[0]);
                yend = Float.parseFloat(cubeArray.get(0).split(" ")[1]);
            } else {
                s = cubeArray.get(i + 1).split(" ");
                xend = Float.parseFloat(s[0]);
                yend = Float.parseFloat(s[1]);
            }
            s = pointArray.get(pointCount - 1).split(" ");
            float pointStartX = Float.parseFloat(s[0]);
            float pointStartY = Float.parseFloat(s[1]);


            temparray = new LinkedList<>();

            float isin = IsInside(xstart, ystart, xend, yend, pointStartX, pointStartY);

            if (isin > 0) {
                flag = 0;
            } else {
                flag = 1;
            }
            for (int j = 0; j < pointCount; j++) {
                s = pointArray.get(j).split(" ");
                float pointEndX = Float.parseFloat(s[0]);
                float pointEndY = Float.parseFloat(s[1]);

                isin = IsInside(xstart, ystart, xend, yend, pointEndX, pointEndY);
                if (isin <= 0) {
                    // 第j个点在内测;
                    if (flag == 0) {
                        //前一个点在外侧;
                        flag = 1;
                        // k=k+1;
                        //求交点，把交点存进结果的新多边形临时数组;
                        String jiaodian = GetJiaoDian(xstart, ystart, xend, yend, pointStartX, pointStartY, pointEndX, pointEndY);
                        temparray.add(jiaodian);
                    }
                    temparray.add(str(pointEndX) + ' ' + str(pointEndY));
                }
                //当前点在外侧;
                else {
                    //前一个点在内侧;
                    if (flag == 1) {
                        flag = 0;
                        String jiaodian = GetJiaoDian(xstart, ystart, xend, yend, pointStartX, pointStartY, pointEndX, pointEndY);
                        temparray.add(jiaodian);
                    }
                }
                // 把这次的终点当成下次的起点;
                pointStartX = pointEndX;
                pointStartY = pointEndY;
            }
            pointArray = temparray;
            pointCount = len(pointArray);
            if (pointCount < 1) {
                return Lists.newArrayList();
            }
        }
        return temparray;
    }

    //计算面积;
    public static float PointsArea(List<String> pointList) {
        float earchWDZC = (float) 40008.08 * 1000;
//        String[] pointArray = pointList.split(",");
        int point_num = pointList.size();
        if (point_num < 3) {
            return 0;
        }
        float wd = Float.parseFloat(pointList.get(0).split(" ")[1]);
        float s = (Float.parseFloat(pointList.get(0).split(" ")[1])) * ((Float.parseFloat(pointList.get(point_num - 1).split(" ")[0])) - (Float.parseFloat(pointList.get(1).split(" ")[0])));
        for (int i = 1; i < point_num; i++) {

            s = s + (Float.parseFloat(pointList.get(i).split(" ")[1])) * (Float.parseFloat(pointList.get(i - 1).split(" ")[0]) - Float.parseFloat(pointList.get((i + 1) % point_num).split(" ")[0]));
        }
        return (float) ((Math.abs(s) / 2) * Math.cos((2 * Math.PI / 360) * wd) * (earchWDZC / 360) * (earchWDZC / 360));

    }

    private static boolean IsPtInPoly(float aLon, float aLat, String pointListstr) {

        /*'' ';
            :param aLon:float 经度;
        :param aLat:float 纬度;
        :param pointList:list[(lon, lat)...]多边形点的顺序需根据顺时针或逆时针，不能乱;
        '' '*/

        //if(isinmap['dddd']==0))
        //   return true;
        String[] pointList = pointListstr.split(",");
        int iSum = 0;
        int iCount = pointList.length;
        if (iCount < 3) {
            return false;
        }
        for (int i = 0; i < iCount; i++) {
            float pLon1 = Float.parseFloat(pointList[i].split(" ")[0]);
            float pLat1 = Float.parseFloat(pointList[i].split(" ")[1]);

            float pLon2;
            float pLat2;
            if (i == iCount - 1) {
                pLon2 = Float.parseFloat(pointList[0].split(" ")[0]);

                pLat2 = Float.parseFloat(pointList[0].split(" ")[1]);
            } else {
                pLon2 = Float.parseFloat(pointList[i + 1].split(" ")[0]);
                pLat2 = Float.parseFloat(pointList[i + 1].split(" ")[1]);
            }
            if (((aLat >= pLat1) && (aLat < pLat2)) || ((aLat >= pLat2) && (aLat < pLat1))) {
                float pLon = 0;

                if (Math.abs(pLat1 - pLat2) > 0) {
                    pLon = pLon1 - ((pLon1 - pLon2) * (pLat1 - aLat)) / (pLat1 - pLat2);

                    if (pLon < aLon) {
                        iSum += 1;
                    }
                }
            }
        }
        if (iSum % 2 != 0) {
            return true;
        } else {
            return false;
        }
    }

    private static int len(String s[]) {
        return s.length;
    }

    private static int len(List s) {
        return s.size();
    }

    private static String str(Object o) {
        return o.toString();
    }

}

